package com.jp.fm.data;

import java.io.IOException;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import net.sf.ehcache.Cache;
import net.sf.ehcache.Element;

import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;

import com.jp.fm.HomeFinanceRunner;

public class AccountType implements Serializable, Comparable<AccountType> {

	/**
	 *
	 */
	private static final long serialVersionUID = 1L;
	private Integer id = null;
	private String name = null;
	private Integer sequence = null;
	public static final String CACHE_NAME = "AccountType";

	private static final String COLUMN_ID = "ID";
	private static final String COLUMN_NAME = "NAME";
	private static final String COLUMN_SEQUENCE = "SEQUENCE";

	public AccountType(final Integer id, final String name,
			final Integer sequence) {
		super();
		this.id = id;
		this.name = name;
		this.sequence = sequence;
	}

	public static List<AccountType> findAll() {

		List<AccountType> ats = new ArrayList<AccountType>();

		// look in cache first
		Cache cache = HomeFinanceRunner.getCache(CACHE_NAME);
		Map<Object, Element> elementMap = cache.getAll(cache
				.getKeysWithExpiryCheck());
		AccountType type = null;
		if (null == elementMap || elementMap.size() == 0) {

			Connection c = null;
			PreparedStatement p = null;
			ResultSet rs = null;

			try {
				c = HomeFinanceRunner.getConnection();

				p = c.prepareStatement("select id, name, sequence from account_type");

				rs = p.executeQuery();

				while (rs.next()) {

					Integer dbId = rs.getInt(COLUMN_ID);

					type = new AccountType(dbId, rs.getString(COLUMN_NAME),
							rs.getInt(COLUMN_SEQUENCE));
					ats.add(type);
					cache.put(new Element(type.getId(), type));
				}

			} catch (SQLException e) {

				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				HomeFinanceRunner.closeConnection(c, p, rs);
			}
		} else {

			for (Iterator<Element> iterator = elementMap.values().iterator(); iterator
					.hasNext();) {
				Element element = iterator.next();

				type = (AccountType) element.getObjectValue();
				ats.add(type);
			}
		}

		return ats;
	}

	public static AccountType findById(final Integer id) {

		AccountType type = null;

		// look in cache first
		Cache cache = HomeFinanceRunner.getCache(CACHE_NAME);
		Element element = cache.get(id);

		if (null == element) {
			Connection c = null;
			PreparedStatement p = null;
			ResultSet rs = null;

			try {
				c = HomeFinanceRunner.getConnection();

				p = c.prepareStatement("select id, name, sequence from account_type where id = ?");
				p.setInt(1, id);

				rs = p.executeQuery();

				while (rs.next()) {

					Integer dbId = rs.getInt(COLUMN_ID);

					if (dbId.equals(id)) {
						type = new AccountType(dbId, rs.getString(COLUMN_NAME),
								rs.getInt(COLUMN_SEQUENCE));
						cache.put(new Element(type.getId(), type));
						cache.put(new Element(type.getName(), type));
						break;
					}
				}

			} catch (SQLException e) {

				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				HomeFinanceRunner.closeConnection(c, p, rs);
			}
		} else {
			type = (AccountType) element.getObjectValue();
		}

		return type;
	}

	public static AccountType findByName(final String name) {

		AccountType type = null;

		// look in cache first
		Cache cache = HomeFinanceRunner.getCache(CACHE_NAME);
		Element element = cache.get(name);

		if (null == element) {
			Connection c = null;
			PreparedStatement p = null;
			ResultSet rs = null;

			try {
				c = HomeFinanceRunner.getConnection();

				p = c.prepareStatement("select id, name, sequence from account_type where name = ?");
				p.setString(1, name);

				rs = p.executeQuery();

				while (rs.next()) {

					String dbName = rs.getString(COLUMN_NAME);

					if (dbName.equals(name)) {
						type = new AccountType(rs.getInt(COLUMN_ID),
								rs.getString(COLUMN_NAME),
								rs.getInt(COLUMN_SEQUENCE));
						cache.put(new Element(type.getId(), type));
						cache.put(new Element(type.getName(), type));
						break;
					}
				}

			} catch (SQLException e) {

				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				HomeFinanceRunner.closeConnection(c, p, rs);
			}
		} else {
			type = (AccountType) element.getObjectValue();
		}

		return type;
	}

	public final Integer getSequence() {
		return this.sequence;
	}

	public final void setSequence(final Integer sequence) {
		this.sequence = sequence;
	}

	public final Integer getId() {
		return this.id;
	}

	public final void setId(final Integer id) {
		this.id = id;
	}

	public final String getName() {
		return this.name;
	}

	public final void setName(final String name) {
		this.name = name;
	}

	@Override
	public final String toString() {
		return ToStringBuilder.reflectionToString(this);
	}

	@Override
	public final int compareTo(final AccountType o) {
		return this.sequence.compareTo(o.getSequence());
	}

	@Override
	public final boolean equals(final Object obj) {

		return EqualsBuilder.reflectionEquals(this, obj, false);
	}

	@Override
	public final int hashCode() {
		return super.hashCode();
	}

}
